home *** CD-ROM | disk | FTP | other *** search
- _STRUCTURED PROGRAMMING COLUMN_
- by Jeff Duntemann
-
-
- [LISTING ONE]
-
- PROGRAM LoopTest; { From "Structured Programming" DDJ 7/91 }
- CONST
- UART : ARRAY[0..4] OF STRING =
- (' faulty','n 8250',' 16450',' 16550',' 16550A');
- VAR
- PortNum : Byte;
- {-----------------------------------------------------------------}
- { FUNCTION DetectComPort by Jeff Duntemann }
- { This function returns a Boolean value indicating whether or not }
- { a National Semiconductor UART (one of 8250B, 16450, 16550, or }
- { 16550A) is present at the COM port passed in the PortNumber }
- { parameter. Don't run this function on serial ports that may be }
- { operating in some sort of background mode; it will probably }
- { disrupt any communication stream currently in progress. }
- {-----------------------------------------------------------------}
- FUNCTION DetectComPort(PortNumber : Integer) : Boolean;
- CONST
- LOOPBIT = $10;
- PortBases : ARRAY[1..4] OF Integer = ($03F8,$02F8,$03E8,$02E8);
- { COM1 COM2 COM3 COM4 }
- VAR
- Holder,HoldMCR,HoldMSR : Byte;
- MCRPort,MSRPort,THRPort,RBRPort : Integer;
- BEGIN
- { Calculate port numbers for the port being looked for: }
- RBRPort := PortBases[PortNumber]; { RBR is at the base address }
- THRPort := RBRPort; { RBR and THR have same I/O address }
- MCRPort := RBRPort + 4; { MCR is at offset 4 }
- MSRPort := RBRPort + 6; { MSR is at offset 6 }
- { Put the UART into loopback test mode: }
- HoldMCR := Port[MCRPort]; { Save existing value of MCR }
- Port[MCRPort] := HoldMCR OR LOOPBIT; { Turn on loopback test mode }
- HoldMSR := Port[MSRPort];
- Port[MCRPort] := $0A OR LOOPBIT; { Put pattern to low 4 bits of MCR }
- { without disabling loopback mode }
- Holder := Port[MSRPort] AND $F0; { Read pattern from hi 4 bits of MSR }
- IF Holder = $90 THEN { The $A pattern is changed to $9 inside UART }
- DetectComPort := True
- ELSE
- DetectComPort := False;
- { Restore previous contents of MSR: }
- Port[MSRPort] := HoldMSR;
- { Take the UART out of loopback mode & restore old state of MCR: }
- Port[MCRPort] := HoldMCR AND (NOT LOOPBIT);
- END;
- {-----------------------------------------------------------------}
- { FUNCTION DetectUARTType by Jeff Duntemann }
- { This function returns a numeric code indicating which UART chip }
- { is present at the selected PortNumber (1-4.) The UART codes }
- { returned are as follows: }
- { 0 : Error; bad UART or no UART at COMn, where n=PortNumber }
- { 1 : 8250; generally (but not always!) present in PC or XT }
- { 2 : 16450; generally present in AT-class machines }
- { 3 : 16550; in PS/2 mod 50/60/early 80. FIFOs don't work! }
- { 4 : 16550A; in later PS/2's. FIFOs fully operative. }
- { NOTE: This routine assumes a UART is "out there" at the port # }
- { specified. Run DetectComPort first to make sure port is there! }
- {-----------------------------------------------------------------}
- FUNCTION DetectUARTType(PortNumber : Integer) : Integer;
- CONST
- PortBases : ARRAY[1..4] OF Integer = ($03F8,$02F8,$03E8,$02E8);
- { COM1 COM2 COM3 COM4 }
- VAR
- ScratchPort,IIRPort,FCRPort : Integer;
- Holder : Byte;
- BEGIN
- { The scratch register is at offset 7 from the comm port base: }
- ScratchPort := PortBases[PortNumber] + 7;
- FCRPort := PortBases[PortNumber] + 2;
- IIRPort := FCRPort; { IIR and FCR are at same offset }
- Port[ScratchPort] := $AA; { Write pattern to the scratch register }
- IF Port[ScratchPort] <> $AA THEN { Attempt to read it back... }
- DetectUARTType := 1 { A UART without a scratch register is an 8250 }
- ELSE
- BEGIN { Now we have to test among the 16450, 16550, and 16550A }
- Port[FCRPort] := $01; { Setting FCR bit 0 on 16550 enables FIFOs }
- Holder := Port[IIRPort] AND $C0; { Read back to FIFO status bits }
- CASE Holder OF
- $C0 : DetectUARTType := 4; { Bits 6 & 7 both set = 16550A }
- $80 : DetectUARTType := 3; { Bit 7 set & bit 6 cleared = 16550 }
- $00 : DetectUARTType := 2; { Neither bit set = 16450 }
- ELSE DetectUARTType := 0; { Error condition }
- END; {CASE}
- Port[FCRPort] := $00; { Don't leave the FIFOs enabled! }
- END;
- END;
-
- BEGIN
- FOR PortNum := 1 TO 4 DO
- BEGIN
- IF DetectComPort(PortNum) THEN
- BEGIN
- Write ('Port COM',PortNum,' is present,');
- Writeln(' using a',UART[DetectUARTType(PortNum)],' UART.');
- END
- ELSE
- Writeln('Port COM',Portnum,' is not present.');
- END;
- END.
-